#include "utils/Logger.h"
#include <ctime>
#include <iomanip>

UniAST::Logger &UniAST::Logger::getLogger(LogLevel level,
                                          const std::string &logFile) {
  static Logger instance(level, logFile);
  return instance;
}

// set log level
void UniAST::Logger::setLogLevel(LogLevel level) {
  std::lock_guard<std::mutex> lock(mtx);
  currentLogLevel = level;
}

UniAST::Logger::Logger(LogLevel level, const std::string &logFile)
    : currentLogLevel(level) {
  this->streamLogLevel = INFO;
  if (!logFile.empty()) {
    outFile.open(logFile, std::ios::out | std::ios::app);
  }
}

UniAST::Logger::~Logger() {
  if (outFile.is_open()) {
    outFile << std::endl;
    outFile.close();
  } else {
    std::cout << std::endl;
  }
}

void UniAST::Logger::logMessage(LogLevel level, const std::string &message) {
  std::string levelStr = logLevelToString(level);
  std::string timeStr = getCurrentTime();

  std::string logMessage = "[" + timeStr + "] [" + levelStr + "] " + message;

  if (outFile.is_open()) {
    outFile << logMessage;
  } else {

    std::cout << logMessage;
  }
}

std::string UniAST::Logger::logLevelToString(LogLevel level) {
  switch (level) {
  case DEBUG:
    return "DEBUG";
  case INFO:
    return "INFO";
  case WARN:
    return "WARN";
  case ERROR:
    return "ERROR";
  default:
    return "UNKNOWN";
  }
}

std::string UniAST::Logger::getCurrentTime() {
  auto now = std::time(nullptr);
  std::tm localTime;

  localtime_r(&now, &localTime); // POSIX系统（Linux, MacOS等）

  std::ostringstream oss;
  oss << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S");
  return oss.str();
}